#include "stdafx.h"

#include "d3dmisc.h"
#include "d3dmath.h"
#include <gl/glu.h>

using namespace D3DMath;

//For convenience
#pragma comment(lib, "glu32.lib") 

//void Path2Mesh(PathPolygon &poly)
//{
    // extrude the path polygon
	/*
    PathExtruder extruder(path_polygon);
    gNumVertices = extruder.Indices.size();
    // Create the vertex buffer.
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( gNumVertices*sizeof(CUSTOMVERTEX),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB ) ) )    {
        return E_FAIL;
    }
    // Fill the vertex buffer.
    CUSTOMVERTEX* pVertices;
    if( FAILED( g_pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 ) ) )
        return E_FAIL;
    for( DWORD i=0; i < gNumVertices; i++ )
    {
        DWORD idx = extruder.Indices[i];
        const double SizeFactor = 1.0 / 10.0;
            // modify the value of SizeFactor if you changed the font size
            // in the call to CreateFont above!
        double x = extruder.Vertices[idx].x * SizeFactor;
        double y = extruder.Vertices[idx].y * SizeFactor;
        double z = extruder.Vertices[idx].z * SizeFactor;

        pVertices[i].position = D3DXVECTOR3(x, y, z);
        pVertices[i].normal = D3DXVECTOR3(
            extruder.Vertices[idx].nx,
            extruder.Vertices[idx].ny,
            extruder.Vertices[idx].nz
            );
        pVertices[i].tu = extruder.Vertices[idx].u;
        pVertices[i].tv = extruder.Vertices[idx].v;
    }
    g_pVB->Unlock();
	*/
//}

typedef void (__stdcall *GluTessCallbackType)();

void String2Path(TCHAR *string) {
    HDC screen_dc = NULL;
    HDC mem_dc = NULL;
    HBITMAP mem_bmp = NULL;
    HFONT h_font = NULL;
    // create an off-screen DC
    mem_dc = CreateCompatibleDC(NULL);
    // retrieve a handle to the screen DC
    screen_dc = GetDC(NULL);
    // create an off-screen bitmap that is compatible to the screen
    mem_bmp = CreateCompatibleBitmap(screen_dc, 300, 300);
    // select the off-screen bitmap into the off-screen DC
    SelectObject(mem_dc, mem_bmp);
    // create TrueType font object
    // (The first parameter to the CreateFont function specifies the font size.
    // Greater values result in higher polygon count and bigger meshes.)
    h_font = CreateFont(100, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 0, "Arial");
    // select the font object into the off-screen DC
    SelectObject(mem_dc, h_font);
    SetBkMode(mem_dc, TRANSPARENT); // try also OPAQUE for a nice effect!

	//Record the path
	BeginPath(mem_dc);
	char *str = ("Extruded!");
    TextOut(mem_dc, 0, 0, str, (int)strlen(str));
    EndPath(mem_dc);

    // create a PathPolygon object from the path in the off-screen DC
	FlattenPath(mem_dc);
	int numPoints = GetPath(mem_dc, 0, 0, 0);
	struct TessContext {
		LPPOINT points;
		LPBYTE types;
		Vec3 *verts;
		
		int *indexList;
		int numInds;
		int numVerts;

		static void __stdcall VertexCB(void *vertexIndexData, TessContext *ctx) {
			int vertexIndex = (int)(size_t)vertexIndexData;
			ctx->indexList[ctx->numInds++] = vertexIndex;
		}
		static void __stdcall CombineCB(GLdouble coords[3], void * vertex_data[4], GLfloat weight[4], void **outData, TessContext *ctx) {
			ctx->verts[ctx->numVerts] = Vec3(coords[0], coords[1], coords[2]);
			*(int*)outData = ctx->numVerts;
			ctx->numVerts++;
		}
		static void __stdcall EdgeFlagCB(bool flag, TessContext *ctx) {
			// don't care
		}
	} context;

	//We assume numVerts > 0
	context.points = new POINT[numPoints];
	context.types = new BYTE[numPoints+1]; //PT_MOVETO or PT_LINETO
	context.numInds = 0;
	context.indexList = new int[numPoints*4]; //TODO: think about how big this should be really
	context.verts = new Vec3[numPoints*2];
	context.numVerts = numPoints;

	GetPath(mem_dc, context.points, context.types, numPoints);
	
	//Alright, let's abuse GLU 
	GLUtesselator *tess = gluNewTess();
	gluTessCallback(tess, GLU_TESS_VERTEX_DATA,  (GluTessCallbackType)&TessContext::VertexCB);
	gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (GluTessCallbackType)&TessContext::CombineCB);
	gluTessCallback(tess, GLU_TESS_EDGE_FLAG_DATA, (GluTessCallbackType)&TessContext::EdgeFlagCB); //make sure we get independent tris

	gluTessBeginPolygon(tess, (void*)&context);
	int i = 0;
	while (i < numPoints) {
		gluTessBeginContour(tess);
		if ((context.types[i]&~1) != PT_MOVETO) DebugBreak();
		do {
			double coord[3] = {context.points[i].x, context.points[i].y, 0};
			context.verts[i].x = (float)coord[0];
			context.verts[i].y = (float)coord[1];
			context.verts[i].z = (float)coord[2];
			gluTessVertex(tess, coord, (void *)(size_t)i);  //pass in the vertex number as custom parameter
			i++;
		} while ((context.types[i]&~1) == PT_LINETO);
		gluTessEndContour(tess);
	}
	//Do the tesselation!
	gluTessEndPolygon(tess);

	//Here, we could use our contours, if we had stored them, to tesselate edges and stuff.
	delete [] context.points;
	delete [] context.types;

	gluDeleteTess(tess);

	// delete the GDI objects
    ReleaseDC(NULL, screen_dc);
    screen_dc = NULL;
    DeleteDC(mem_dc);
    mem_dc = NULL;
    DeleteObject(mem_bmp);
    mem_bmp = NULL;
    DeleteObject(h_font);
    h_font = NULL;
//	Path2Mesh(path_polygon);
}

